package handler

import (
	"context"
	"errors"
	"gorm.io/gorm"
	. "rbac/models"
	pb "rbac/proto/rbacRole"
	"strconv"
	"time"
)

type RbacRole struct{}

// 获取角色
func (e *RbacRole) RoleGet(ctx context.Context, req *pb.RoleGetRequest, res *pb.RoleGetResponse) error {
	var roleList []Role
	where := "1=1"
	if req.Id > 0 {
		where += " AND id=" + strconv.Itoa(int(req.Id))
	}
	DB.Where(where).Find(&roleList)
	var tempList []*pb.RoleModel
	for _, v := range roleList {
		tempList = append(tempList, &pb.RoleModel{
			Id:          int64(v.ID),
			Title:       v.Title,
			Description: v.Description,
			Status:      int64(v.Status),
			AddTime:     int64(v.AddTime),
		})
	}
	res.RoleResult = tempList
	return nil
}

// 增加角色
func (e *RbacRole) RoleAdd(ctx context.Context, req *pb.RoleAddRequest, res *pb.RoleAddResponse) error {
	role := Role{
		Title:       req.Title,
		Description: req.Description,
		Status:      1,
		AddTime:     int(time.Now().Unix()),
	}
	err := DB.Create(&role).Error
	if err != nil {
		res.Success = false
		res.Message = "增加角色失败"
		return err
	}
	res.Success = true
	res.Message = "增加角色成功"
	return nil
}

// 编辑角色
func (e *RbacRole) RoleEdit(ctx context.Context, req *pb.RoleEditRequest, res *pb.RoleEditResponse) error {
	var role Role
	DB.Where("id = ?", req.Id).Take(&role)
	if role.ID == 0 {
		res.Success = false
		res.Message = "角色不存在"
		return errors.New("角色不存在")
	}
	role.Title = req.Title
	role.Description = req.Description
	role.Status = int(req.Status)
	err := DB.Save(&role).Error
	if err != nil {
		res.Success = false
		res.Message = "修改角色失败"
		return errors.New("修改角色失败")
	}
	res.Success = true
	res.Message = "修改角色成功"
	return nil
}

// 删除角色
func (e *RbacRole) RoleDelete(ctx context.Context, req *pb.RoleDeleteRequest, res *pb.RoleDeleteResponse) error {
	var role Role
	DB.Where("id = ?", req.Id).Take(&role)
	if role.ID == 0 {
		res.Success = false
		res.Message = "用户不存在"
		return nil
	}
	err := DB.Delete(&role).Error
	if err != nil {
		res.Success = false
		res.Message = "删除失败"
		return err
	}
	res.Success = true
	res.Message = "删除成功"
	return nil
}

// 获取角色权限
func (e *RbacRole) RoleAuth(ctx context.Context, req *pb.RoleAuthRequest, res *pb.RoleAuthResponse) error {
	var role Role
	DB.Where("id = ?", req.Id).Take(&role)
	if role.ID == 0 {
		return nil
	}
	// 检索权限和角色的映射
	var roleAccessList []RoleAccess
	DB.Where("role_id = ?", role.ID).Find(&roleAccessList)
	// 创建map映射
	roleAccessMap := make(map[int]int)
	for _, v := range roleAccessList {
		roleAccessMap[v.AccessID] = v.AccessID
	}
	// 检索全部顶级权限和预加载全部次级权限
	var accessList []Access
	DB.Where("module_id = ?", 0).Preload("AccessItem", func(DB *gorm.DB) *gorm.DB {
		return DB.Order("access.sort DESC")
	}).Order("sort DESC").Find(&accessList)
	// 遍历所有权限
	for i := 0; i < len(accessList); i++ {
		if _, ok := roleAccessMap[accessList[i].ID]; ok {
			accessList[i].Checked = true
		}
		// 遍历所有次级权限
		for j := 0; j < len(accessList[i].AccessItem); j++ {
			if _, ok := roleAccessMap[accessList[i].AccessItem[j].ID]; ok {
				accessList[i].AccessItem[j].Checked = true
			}
		}
	}
	var tempList []*pb.AccessModel
	// 类型转换
	for _, v := range accessList {
		var tempItemList []*pb.AccessModel
		for _, t := range v.AccessItem {
			tempItemList = append(tempItemList, &pb.AccessModel{
				Id:          int64(t.ID),
				ModuleName:  t.ModuleName,
				ActionName:  t.ActionName,
				Type:        int64(t.Type),
				Url:         t.Url,
				ModuleId:    int64(t.ModuleID),
				Sort:        int64(t.Sort),
				Description: t.Description,
				Status:      int64(t.Status),
				AddTime:     int64(t.AddTime),
				Checked:     t.Checked,
			})
		}
		tempList = append(tempList, &pb.AccessModel{
			Id:          int64(v.ID),
			ModuleName:  v.ModuleName,
			ActionName:  v.ActionName,
			Type:        int64(v.Type),
			Url:         v.Url,
			ModuleId:    int64(v.ModuleID),
			Sort:        int64(v.Sort),
			Description: v.Description,
			Status:      int64(v.Status),
			AddTime:     int64(v.AddTime),
			Checked:     v.Checked,
			AccessItem:  tempItemList,
		})
	}
	res.AccessList = tempList
	return nil
}

// 执行角色授权
func (e *RbacRole) RoleDoAuth(ctx context.Context, req *pb.RoleDoAuthRequest, res *pb.RoleDoAuthResponse) error {
	// 删除当前角色的全部权限
	DB.Where("role_id = ?", req.RoleId).Delete(&RoleAccess{})
	var roleAccess RoleAccess
	for _, v := range req.AccessIds {
		accessId, _ := strconv.Atoi(v)
		roleAccess = RoleAccess{
			RoleID:   int(req.RoleId),
			AccessID: accessId,
		}
		DB.Create(&roleAccess)
	}
	res.Success = true
	res.Message = "授权成功"
	return nil
}

// 权限判断
func (e *RbacRole) MiddleWareAuth(ctx context.Context, req *pb.MiddleWareAuthRequest, res *pb.MiddleWareAuthResponse) error {
	var RoleAccessList []RoleAccess
	DB.Where("role_id = ?", req.RoleId).Find(&RoleAccessList)
	// 创建权限map映射
	roleAccessMap := make(map[int]int)
	for _, v := range RoleAccessList {
		roleAccessMap[v.AccessID] = v.AccessID
	}
	// 判断当前权限
	var access Access
	DB.Where("url = ?", req.UrlPath).Take(&access)
	if _, ok := roleAccessMap[access.ID]; !ok {
		res.HasPermission = false
		return nil
	}
	res.HasPermission = true
	return nil
}
